﻿//-----------------------------------------------------------------------
// <copyright file="ReSign.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Andy Reeves [Updated: 22-2-08 Mike Fourie. Code Cleanup. 25-2-08 Mike Fourie. CodePlex update.]</author>
// <email>andyr</email>
// <date>2004-03-23</date>
// <summary>Adds a strong name to the specified assemblies.</summary>
//-----------------------------------------------------------------------
namespace Microsoft.Sdc.Tasks.Tools.StrongName
{
    using System;
    using System.IO;
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;

    /// <summary>
    /// Adds a strong name to the specified assemblies.
    /// </summary>          
    /// <remarks>
    /// <code><![CDATA[
    /// <Tools.StrongName.ReSign   Assemblies="assemblies"
    ///             Runtime="runtime"
    ///             Key="key">
    /// </Tools.StrongName.ReSign>
    /// ]]></code>
    /// <para>where:</para>
    /// <para><i>assemblies (Required)</i></para>
    /// <para>The fullpaths to the assemblies to add the strong name to. These assemblies must exist or an exception will be thrown.</para>
    /// <para><i>runtime</i></para>
    /// <para>The runtime version to use for the signing. Valid values are "1.0", "1.1" or "2.0".</para>
    /// <para><i>key</i></para>
    /// <para>The path to the .snk file to be used to re-sign.</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <ItemGroup>
    ///         <Assemblies Include="Microsoft.Sdc.Tasks.Configuration.Tasks.dll" />
    ///         <Assemblies Include="Microsoft.Sdc.Tasks.Configuration.Tasks.Test.dll" />
    ///     </ItemGroup>
    ///     <Target Name="Test" >
    ///         <Tools.StrongName.ReSign
    ///             ContinueOnError="true"
    ///             Assemblies="@(Assemblies->'%(FullPath)')" 
    ///             Runtime="2.0"
    ///             KeyFile="$(CurrentFolder)\secret\PrivateKey.snk" /> 
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>
    public sealed class ReSign : ToolTaskBase
    {
        /// <summary>The path to the snk file to be used to re-sign</summary>
        [Required]
        public string KeyFile
        {
            get { return (string)Bag["KeyFile"]; }
            set { Bag["KeyFile"] = value; }
        }

        /// <summary>The runtime version to use for the signing i.e. 1.0, 1.1 or 2.0 </summary>
        [Required]
        public string Runtime
        {
            get { return (string)Bag["Runtime"]; }
            set { Bag["Runtime"] = value; }
        }

        /// <summary> Property for String array variable Assemblies. </summary>
        /// <returns> Returns a String array value. </returns>
        /// <value> Accepts a String array value. </value>
        [Required]
        public string[] Assemblies
        {
            get { return ((string[])Bag["Assemblies"]); }
            set { Bag["Assemblies"] = value; }
        }

        /// <summary>
        /// The name of the exe we call.
        /// </summary>
        /// <value>The name of the exe we call.</value>
        protected override string ToolName
        {
            get { return "Sn.exe"; }
        }

        /// <summary>
        /// Full calculated path to tool including exe name
        /// </summary>
        /// <returns>Defaults to default install location of Sn.exe</returns>
        protected override string GenerateFullPathToTool()
        {
            string pathToTool = Path.Combine(Microsoft.Sdc.Tasks.Configuration.Utilities.GetPathToSDK(this.Runtime), @"bin\" + this.ToolName);

            if (pathToTool == null)
            {
                Log.LogError("StrongName.NotFound");
            }

            return pathToTool;
        }       

        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            #region Execute code
            Log.LogMessageFromResources(MessageImportance.Low, "StrongName.Starting");

            foreach (string assembly in this.Assemblies)
            {
                FileInfo fi = new FileInfo(assembly);
                if (fi.Exists)
                {
                    CommandLineBuilder commandLine = new CommandLineBuilder();
                    commandLine.AppendSwitch("-q");
                    commandLine.AppendSwitch("-R");
                    commandLine.AppendFileNameIfNotNull(assembly);
                    commandLine.AppendFileNameIfNotNull(this.KeyFile);

                    Log.LogMessageFromResources(MessageImportance.Low, "StrongName.AddingStrongName", assembly);

                    ExecuteTool(this.ComputePathToTool(), String.Empty, commandLine.ToString());
                
                    commandLine = new CommandLineBuilder();
                    commandLine.AppendSwitch("-vf");
                    commandLine.AppendFileNameIfNotNull(assembly);
                    ExecuteTool(this.ComputePathToTool(), String.Empty, commandLine.ToString());
                }
                else
                {
                    throw new TaskException("General.AssemblyNotExist", assembly);
                }
            }

            #endregion
        }
    }
}